use async_std::io;
use async_std::io::{BufReader,BufWriter};
use async_std::net::{TcpListener, TcpStream};
use async_std::prelude::*;
use async_std::task;
use local_ip_address::local_ip;
use std::borrow::BorrowMut;
use std::collections::HashMap;
use tauri::async_runtime::Mutex;
use serde_json::{Result, Value};
use tauri::{Manager,Window};
use serde::{Serialize, Deserialize};
use futures::{select};
pub struct AppTcpServer{
    pub conn_map:Mutex<HashMap<String,Vec<TcpStream>>>
}
#[derive(Debug,Serialize,Clone,Deserialize)]
struct ClientInfoPayload{
    ip:String,
    port:String,
    id:String,
}
#[derive(Debug,Serialize,Clone,Deserialize)]
struct WriterPayload{
    message:String
}
#[derive(Debug,Serialize,Clone,Deserialize)]
struct ReaderPayload{
    index:String,
    count:String,
    message:String
}
#[tauri::command]
pub fn getIP() ->String{
    println!("get local ip");
    local_ip().unwrap().to_string()
}
//目前只能一行一行读，遇到回车符代表读取到一次
pub async fn read_process(window: Window,index:String,count:i32,mut reader:TcpStream,write_handler: tauri::EventHandler){
    let info: ClientInfoPayload = ClientInfoPayload{
        ip:reader.peer_addr().unwrap().ip().to_string(),
        port:reader.peer_addr().unwrap().port().to_string(),
        id:count.to_string()
    };
    let mut buf_reader = BufReader::new(&reader); // 2
    loop{
        let mut message = String::new();
        let res = buf_reader.read_line(&mut message).await;
        match  res{
                Ok(size) =>  {
                    println!("{}",size);  //size为0则客户端断开
                    if size!=0{
                        let p: ReaderPayload  = ReaderPayload{
                            index:index.clone(),
                            count:count.to_string(),
                            message:format!("{}:{}   ",info.ip,info.port)+message.as_str()
                        };
                        window.emit_all(format!("s{}r",index).as_str(), p);
                    }
                    else {  //连接断开了
                        let p: ReaderPayload  = ReaderPayload{
                            index:index.clone(),
                            count:count.to_string(),
                            message:"closed".to_string()
                        };
                        window.emit_all(format!("s{}c",index).as_str(), p);
                        window.unlisten(write_handler);
                        break;
                    }
                },
                Err(e)  => {
                    println!("err:{:?}",e);
                }
        }
    }
}
pub async fn process(window: Window,count:i32,index:String,mut stream: TcpStream) -> io::Result<()> {
    println!("Accepted from: {}", stream.peer_addr()?);
    let p: ClientInfoPayload = ClientInfoPayload{
        ip:stream.peer_addr().unwrap().ip().to_string(),
        port:stream.peer_addr().unwrap().port().to_string(),
        id:count.to_string()
    };
    window.emit_all(format!("s{}",index).as_str(), p);
    let  reader = stream.clone();
    //let  mut writer =stream;
    let listen_handler: tauri::EventHandler=window.listen_global(format!("s{}w{}",index,count).as_str(),  move |event: tauri::Event| {
        let mut writer = stream.clone();
        println!("{:?}",event.payload().unwrap());
        let p: WriterPayload = serde_json::from_str(event.payload().unwrap()).unwrap();
        writer.write_all(p.message.as_bytes());
    });
    task::spawn(read_process(window.clone(),index.clone(),count,reader,listen_handler));
    Ok(())
}
pub async fn createServer(window: Window,index:String,ip_port:String)->io::Result<()>{
    let listener = TcpListener::bind(ip_port).await?;
    let mut client_count = 0;
    println!("Listening on {}", listener.local_addr()?);
    let mut incoming = listener.incoming();
    while let Some(stream) = incoming.next().await {
        let mut stream = stream?;
        task::spawn(process(window.clone(),client_count,index.clone(),stream));
        client_count+=1;
    }
    Ok(())
}
#[tauri::command]
pub fn newServer(window: Window,index:String,ip: &str,port:&str) -> bool {
    println!("{}",format!("{}:{}",ip,port));
    task::spawn(createServer(window,index,format!("{}:{}",ip,port)));
    true
}